/**
* @file
* This file is used to setup configuration file,
* send and receive data between networks,
* log messages to file, and encrypt passwords
*/
#ifndef UTILS_H
#define UTILS_H

//-------------------------------------------------------
// Header Files
//-------------------------------------------------------
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h> // for bool
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h> // For crypt()
#include "storage.h"
#include <time.h> // to set up time for logger() calls

//-------------------------------------------------------
// Constants
//-------------------------------------------------------
// comment character for configuration file
// Note: Can only be placed on a new line by itself and not after anything
static const char CONFIG_COMMENT_CHAR = '#';
#define MAX_CMD_LEN (1024 * 8) ///< maximum command's length given by client to server
#define LOG(x)  {printf x; fflush(stdout);} ///< printf x to stdout, flush without needing '\n' character
					    // @Note x will contain the braces as well ("...",...)
#ifdef NDEBUG
#define DBG(x)  {}
#else
#define DBG(x)  {printf x; fflush(stdout);}
#endif

#define MAX_MSG_LEN 80 // Maximum message length for logger()
char message[MAX_MSG_LEN+1]; // for logger(), @note: Will segfault in sprintf() is

FILE *fileServer; // file to be used for logger() in server.c
FILE *fileClient; // file to be used for logger() in client.c and storage.c

/// A structure to store the configuration file's parameters
// Note: Does not store the table data currently
struct config_params
{
    char server_host[MAX_HOST_LEN];
    int server_port;
    char username[MAX_USERNAME_LEN];
    char password[MAX_ENC_PASSWORD_LEN];
    char data_directory[MAX_PATH_LEN]; // for Milestone 4
};

/// A structure to check if there is duplicate or missing parameter names
struct check_duplmis
{
    int host, port, username, password, table;
};

/// An initializing function to set configs to 0
int initialCheck( struct check_duplmis *check);

// Tables
char **tables; // array of tables
// @note Current number of tables is stored in check->table

/// Checks and parses the names of the table and key
int checkName(char *msg);
/// Checks and parses the value pertaining to a key and table
int checkValue(char *msg);

/// Gets a line from std in to parameter output up to max
int getLine(char* output, int max);

/// Returns number of digits number contains. EX: 1234 returns 4, 0 returns 1
int numDigits(int number);

//-------------------------------------------------------
// Utility Functions
//-------------------------------------------------------

// Network Protocol Sending functions

/**
* This function sends all data to sock
* @param sock The connfd to be sent to
* @param buf the buffer to store data to be sent
* @param len Maximum size of buf to send
*/
int sendall(const int sock, const char *buf, const size_t len);

/**
*  This function receives all data from sock
* @param sock The sockfd to be received from
* @param buf The buffer to store data received
* @param buflen Maximum size to be received
*/
int recvline(const int sock, char *buf, const size_t buflen);


/* @note This is the original used function prototype
*   int read_config(const char *config_file, struct config_params *params);
* This function reads the configuration file and processes it
* @return 0 if success, -1 otherwise
*/
int read_config(const char *config_file, struct config_params *params, struct check_duplmis *check);

/**
* This function processes one line from the config file
* and stores its value into config_params
* Called by process_config()
* @return -1 if unsuccessful
*/
int process_config_line(char *line, struct config_params *params, struct check_duplmis *check);

//-----------------------------------------------
// New Made Functions
//-----------------------------------------------

/// To log messages
void logger(FILE *file, char *message);

/// To close the logging files
void Fclose(int logger, int serverFile);

/// Prints out the user menu
void menu();

//-----------------------------
// Wrapper Functions
//-----------------------------

/// Creates a socket
int Socket(int family, int type, int protocol);
/// Accepts a peer socket
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
/// Binds a host socket to the server
void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
/// This function connects to a host socket
int ConnectServ(int fd, const struct sockaddr *sa, socklen_t salen);
/// This function listens for peer sockets
void Listen(int fd, int backlog);
/// Closes the connection between client and server
void Close(int fd);

//----------------------------------
// Encryption
//----------------------------------
#define DEFAULT_CRYPT_SALT "xx"
char *generate_encrypted_password(const char *passwd, const char *salt);
#endif
